package pacificlms.Verifiable.Database;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.swing.JOptionPane;
import pacificlms.Error.ErrorHandle;
import pacificlms.MasterConnection;
import pacificlms.Verifiable.*;

/**
 * Checkout is a child of VerifiableObject dealing with check outs
 * Since all fields are get/set they are not individually commented
 * @author Brian Hume
 */
public class CheckOut extends VerifiableObject
{
    @Override
    public String TableName() {
        return "CheckOut";
    }
    
    private String CheckOutID;
    @VerifyAnnotation(ApplicationName="Check Out ID", DBName="CheckOutID",  Type=TypeEnum.NUMERICSTRING, Length=11, PrimaryKey=true, NotNull=false)
    public String CheckOutID(String value)
    {
        return CheckOutID = StandardProcess(CheckOutID, value);
    }
    
    private String ResourceCode;
    @VerifyAnnotation(ApplicationName="Resource Code", DBName="ResourceCode",  Type=TypeEnum.STRING, Length=50, Editable=false, LookupDBTable="Copy", LookupDBField="ResourceCode")
    public String ResourceCode(String value)
    {
        return ResourceCode = StandardProcess(ResourceCode, value);
    }
    
    
    private String CopyNumber;
    @VerifyAnnotation(ApplicationName="Copy Number", DBName="CopyNumber",  Type=TypeEnum.NUMERICSTRING, Length=11, Editable=false, LookupDBTable="Copy", LookupDBField="CopyNumber")
    public String CopyNumber(String value)
    {
        return CopyNumber = StandardProcess(CopyNumber, value);
    }
    
    
    private String IdentityNumber;
    @VerifyAnnotation(ApplicationName="Identity Number", DBName="IdentityNumber",  Type=TypeEnum.NUMERICSTRING, Length=8, Editable=false, PrimaryKey=true, LookupDBTable="Member", LookupDBField="IdentityNumber")
    public String IdentityNumber(String value)
    {
        return IdentityNumber = StandardProcess(IdentityNumber, value);
    }
    
    
    private String DueDate;
    @VerifyAnnotation(ApplicationName="Due Date", DBName="DueDate",  Type=TypeEnum.DATE, Length=50)
    public String DueDate(String value)
    {
        return DueDate = StandardProcess(DueDate, value);
    }
    
    
    private String CheckInDate;
    @VerifyAnnotation(ApplicationName="Check In Date", DBName="CheckInDate",  Type=TypeEnum.DATE, Length=50, NotNull=false)
    public String CheckInDate(String value)
    {
        return CheckInDate = StandardProcess(CheckInDate, value);
    }
    
    
    private String Finished;
    @VerifyAnnotation(ApplicationName="Finished", DBName="Finished",  Type=TypeEnum.STRING, Length=5)
    public String Finished(String value)
    {
        return Finished = StandardProcess(Finished, value);
    }
    public boolean GetFinishedBoolean()
    {
        if (Finished.equalsIgnoreCase("TRUE") || Finished.equalsIgnoreCase("1"))
        {
            return true;
        }
        if (Finished.equalsIgnoreCase("FALSE") || Finished.equalsIgnoreCase("0"))
        {
            return false;
        }
        return false;
    }
    
    private String CopyStatus;
    @VerifyAnnotation(ApplicationName="Copy Status", DBName="CopyStatus",  Type=TypeEnum.ENUM, Length=20, EnumList={"checked out", "returned", "damaged", "lost"})
    public String CopyStatus(String value)
    {
        return CopyStatus = StandardProcess(CopyStatus, value);
    }
    
    
    private String LateFine;
    @VerifyAnnotation(ApplicationName="Late Fine", DBName="LateFine",  Type=TypeEnum.REALNUMBER, Length=20)
    public String LateFine(String value)
    {
        return LateFine = StandardProcess(LateFine, value);
    }
    
    
    private String CopyConditionFine;
    @VerifyAnnotation(ApplicationName="Copy Condition Fine", DBName="CopyConditionFine",  Type=TypeEnum.REALNUMBER, Length=20)
    public String CopyConditionFine(String value)
    {
        return CopyConditionFine = StandardProcess(CopyConditionFine, value);
    }
    
    
    private String Payment;
    @VerifyAnnotation(ApplicationName="Payment", DBName="Payment",  Type=TypeEnum.REALNUMBER, Length=20)
    public String Payment(String value)
    {
        return Payment = StandardProcess(Payment, value);
    }
    
    
    private String RenewalCount;
    @VerifyAnnotation(ApplicationName="Renewal Count", DBName="RenewalCount",  Type=TypeEnum.NUMERICSTRING, Length=11)
    public String RenewalCount(String value)
    {
        return RenewalCount = StandardProcess(RenewalCount, value);
    }

    @Override
    protected boolean ExtraVerification()
    {
        if (Finished.equalsIgnoreCase("TRUE") || Finished.equalsIgnoreCase("FALSE") ||
            Finished.equalsIgnoreCase("1") || Finished.equalsIgnoreCase("0"))
        {
            if (Finished.equalsIgnoreCase("TRUE")) Finished = "1";
            if (Finished.equalsIgnoreCase("FALSE")) Finished = "0";
            return true;
        }
        
        ErrorHandle.Display("Input Error", "Finished must be either true or false", null, true);
        return false;
    }
    
    @Override
    public String toString()
    {
        String Str = "[" + ResourceCode + "] copy#"+CopyNumber +" checked out by member #"+ IdentityNumber;
        if (GetFinishedBoolean())
        {
            Str = Str + " checked in on " + CheckInDate;
            if (CopyStatus.equalsIgnoreCase("returned"))
            {
                Str = Str + " with the condition of " + CopyStatus;
            }
        }
        else if (0==0)//fixme if due in future
        {
            Str = Str + " due on " + DueDate;
        }
        else
        {
            Str = "Late " + Str + " was due on " + DueDate;
        }
        
        double LateFineNum = GetNumber(LateFine);
        double CondFineNum = GetNumber(CopyConditionFine);
        double PaymentNum = GetNumber(Payment);
        if (LateFineNum != 0 || CondFineNum != 0)
        {
            if (LateFineNum + CondFineNum < PaymentNum)
            {
                Str = Str + " a fully paid fine";
            }
            else if (PaymentNum != 0)
            {
                Str = Str + " a fine of $" + String.valueOf(LateFineNum + CondFineNum) + " and a partial payment of $" + String.valueOf(PaymentNum);
            }
            else
            {
                Str = Str + " a fine of $" + String.valueOf(LateFineNum + CondFineNum);
            }
        }
    
        return Str;
    }
    
    public static int CheckoutAmount(Member Memb)
    {
        CheckOut Outs = new CheckOut();
        Outs.IdentityNumber(Memb.IdentityNumber(null));
        Outs.Finished("0");
        
        String SQL = Outs.FindIdenticalSQL();
        SQL = SQL.replace("*", "Count(*) AS CheckCount");
        
        try
        {
            Connection con = MasterConnection.getInstance();
            Statement stmt = con.createStatement();
            ResultSet rs=stmt.executeQuery(SQL);
            
            rs.next();
            int Count = rs.getInt("CheckCount");
            
            return Count;
        }
        catch(Exception Ex)
        {
            JOptionPane.showMessageDialog(null, "Database error, please try again later\n" + Ex.getMessage(), "Database Error", JOptionPane.ERROR_MESSAGE);
            return 0;
        }
    }
}
